<!DOCTYPE html>

<html lang="en" data-content_root="../../">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>Sounds &#8212; Pytch  documentation</title>
    <link rel="stylesheet" type="text/css" href="../../_static/pygments.css?v=03e43079" />
    <link rel="stylesheet" type="text/css" href="../../_static/classic.css?v=36340f97" />
    <link rel="stylesheet" type="text/css" href="../../_static/css/pytch-classic.css?v=0321735e" />
    
    <script src="../../_static/documentation_options.js?v=7f41d439"></script>
    <script src="../../_static/doctools.js?v=9bcbadda"></script>
    <script src="../../_static/sphinx_highlight.js?v=dc90522c"></script>
    
    <link rel="icon" href="../../_static/favicon.ico"/>
    <link rel="author" title="About these documents" href="../../about.html" />
    <link rel="index" title="Index" href="../../genindex.html" />
    <link rel="search" title="Search" href="../../search.html" />
    <link rel="next" title="Tutorials" href="tutorials.html" />
    <link rel="prev" title="Clones" href="clones.html" /> 
  </head><body>
<div class="NavBar">
  <a href="../../../app/"><h1>Pytch</h1></a>
  <ul>
    <a href="https://pytch.scss.tcd.ie/"><li>About Pytch</li></a>
    <a href="../../index.html"><li>Help</li></a>
    <a href="../../../app/tutorials/"><li>Tutorials</li></a>
    <a href="../../../app/my-projects/"><li>My projects</li></a>
  </ul>
</div>
<div class="warning-work-in-progress">
  <p>These help pages are incomplete — we are working on it!</p>
</div>
  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <section id="sounds">
<h1>Sounds<a class="headerlink" href="#sounds" title="Link to this heading">¶</a></h1>
<p>There is a distinction between a <code class="docutils literal notranslate"><span class="pre">Sound</span></code>, which contains all the data
to describe a sound, and a <code class="docutils literal notranslate"><span class="pre">SoundPerformance</span></code>, which represents one
occasion of playing some sound. These map fairly closely to the Web
Audio concepts of <code class="docutils literal notranslate"><span class="pre">AudioBuffer</span></code> and <code class="docutils literal notranslate"><span class="pre">AudioBufferSource</span></code>
respectively.</p>
<section id="mix-buses">
<h2>Mix buses<a class="headerlink" href="#mix-buses" title="Link to this heading">¶</a></h2>
<p>We want to mimic the Scratch behaviour of each individual sprite
instance having its own volume, which can be set independently, and
which controls the gain of all (possibly concurrent) sounds played by
that sprite instance.  In Pytch, the model is that when a sprite
instance starts playing a sound, it does so into a “mix bus”
associated with that sprite instance.  Each mix bus has a gain, which
has a default value of 1.0, and can be set and read.  Gains less than
0.0 or greater than 1.0 should not be used; this mimics Scratch
behaviour.</p>
<p>A mix bus is identified by its <em>name</em>, a string.  Pytch uses the
sprite-instance’s <code class="docutils literal notranslate"><span class="pre">info_label</span></code> for this, which consists of the class
name and a numeric instance ID joined with a hyphen.</p>
</section>
<section id="global-sound-manager-object">
<h2>Global “sound manager” object<a class="headerlink" href="#global-sound-manager-object" title="Link to this heading">¶</a></h2>
<p>There is a Skulpt/Pytch-global <code class="docutils literal notranslate"><span class="pre">sound_manager</span></code> object.  It keeps
track of a collection of mix buses, ensuring that each one has its own
gain.  The object provides methods:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">async_load_sound(tag,</span> <span class="pre">url_or_path)</span></code> — return (a Promise resolving
to) a <code class="docutils literal notranslate"><span class="pre">Sound</span></code> object</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">stop_all_performances()</span></code> — cancel all running
<code class="docutils literal notranslate"><span class="pre">SoundPerformance</span></code>s</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">reset()</span></code> — set the sound-manager’s state such that it is as if it
was freshly constructed</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">set_mix_bus_gain(mix_bus_name,</span> <span class="pre">gain)</span></code> — set the gain of the
mixing bus with the given <code class="docutils literal notranslate"><span class="pre">mix_bus_name</span></code> to <code class="docutils literal notranslate"><span class="pre">gain</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">get_mix_bus_gain(mix_bus_name)</span></code> — return the gain of the mixing
bus with the given <code class="docutils literal notranslate"><span class="pre">mix_bus_name</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">one_frame()</span></code> — do whatever housekeeping is required internally for
the sound-manager</p></li>
</ul>
<p>The client (test or browser) is responsible for calling
<code class="docutils literal notranslate"><span class="pre">one_frame()</span></code>; we don’t do this in the <code class="docutils literal notranslate"><span class="pre">Project</span></code>, to separate these
concerns, and in case we ever have multiple concurrent projects.</p>
</section>
<section id="sound-object">
<h2><code class="docutils literal notranslate"><span class="pre">Sound</span></code> object<a class="headerlink" href="#sound-object" title="Link to this heading">¶</a></h2>
<p>Created by the sound-manager’s <code class="docutils literal notranslate"><span class="pre">async_load_sound()</span></code> method. Has the
single method</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">launch_new_performance(mix_bus_name)</span></code> — create and start playing
a new performance of this sound on the mixing bus with the given
<code class="docutils literal notranslate"><span class="pre">mix_bus_name</span></code></p></li>
</ul>
<p>and the property</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">tag</span></code> — a short human-useful string for diagnostic purposes, set
from the <code class="docutils literal notranslate"><span class="pre">tag</span></code> argument to <code class="docutils literal notranslate"><span class="pre">async_load_sound()</span></code></p></li>
</ul>
</section>
<section id="soundperformance-object">
<h2><code class="docutils literal notranslate"><span class="pre">SoundPerformance</span></code> object<a class="headerlink" href="#soundperformance-object" title="Link to this heading">¶</a></h2>
<p>Created by the <code class="docutils literal notranslate"><span class="pre">launch_new_performance()</span></code> method of a <code class="docutils literal notranslate"><span class="pre">Sound</span></code>. Has
the properties</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">tag</span></code> — diagnostic tag for human consumption; the <code class="docutils literal notranslate"><span class="pre">tag</span></code> of the
<code class="docutils literal notranslate"><span class="pre">Sound</span></code> of which this is a performance</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">has_ended</span></code> — indicates whether the performance has ended or not
(if not, the performance is still going)</p></li>
</ul>
<p>and the single method</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">stop()</span></code> — interrupt the performance, stopping any noise, and
marking the performance as having ended</p></li>
</ul>
<p>It is not an error to call <code class="docutils literal notranslate"><span class="pre">stop()</span></code> on an already-ended performance.</p>
</section>
<section id="registration-of-sounds">
<h2>Registration of sounds<a class="headerlink" href="#registration-of-sounds" title="Link to this heading">¶</a></h2>
<p>An actor (sprite or stage) Python class should have a class-level
attribute <code class="docutils literal notranslate"><span class="pre">Sounds</span></code> which is a list of 2-element tuples (<em>name</em>,
<em>url</em>). The <em>url</em> should point to a sound file of supported format. The
<em>name</em> is used in Actor methods to be described next.</p>
</section>
<section id="actor-methods-for-playing-sounds">
<h2>Actor methods for playing sounds<a class="headerlink" href="#actor-methods-for-playing-sounds" title="Link to this heading">¶</a></h2>
<p>An actor has the sound-related methods</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">self.start_sound(name)</span></code> — launch a new performance of the given
sound, and continue execution of the current thread immediately</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.play_sound_until_done(name)</span></code> — launch a new performance of
the given sound, and pause the calling thread’s execution until the
sound has finished playing</p></li>
</ul>
<p>Implemented via a syscall which uses the global sound-manager. The
‘until done’ variant puts the thread to sleep; the has_ended property is
polled to know when to wake it.</p>
<p>Sound manager separate one-frame() call; serves pretty different
purposes in test and real; not fully convinced this is a clean design;
could have instead had the project’s one-frame() call the
sound-manager’s but kept separate in case ever have more than one
project.</p>
</section>
<section id="real-browser-based-sound-manager">
<h2>Real browser-based sound-manager<a class="headerlink" href="#real-browser-based-sound-manager" title="Link to this heading">¶</a></h2>
<p>Sound is async-loaded by decoding from array-buffer, and creating Sound
from it. Sound can create buffer-source, which is wrapped in
sound-performance.</p>
<p>Small wrinkle because can’t create running audio-context without user
gesture, so have to defer creating sound-manager (with its
audio-context) until first ‘BUILD’ click.</p>
<p>Red-flag stops all sounds, which means we need to track all running
performances. Add them to list when launched. One-frame culls all
completed performances from that list.</p>
</section>
<section id="testing-mock-sound-manager">
<h2>Testing / mock sound-manager<a class="headerlink" href="#testing-mock-sound-manager" title="Link to this heading">¶</a></h2>
<p>Knows how many frames to wait before declaring a performance ‘done’. The
<code class="docutils literal notranslate"><span class="pre">one_frame()</span></code> method allows the sound-manager to count elapsed frames.</p>
</section>
</section>


            <div class="clearer"></div>
          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="Main">
        <div class="sphinxsidebarwrapper"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../webapp/user/index.html">Using the Pytch web app</a></li>
<li class="toctree-l1"><a class="reference internal" href="../user/index.html">Writing Pytch programs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../about.html">About Pytch</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../contact.html">Contact</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../../developer.html">Developer documentation</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../../developer/development-setup.html">Development setup</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../developer/design-overview.html">Design overview</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html">VM</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="overview.html">Overview</a></li>
<li class="toctree-l3"><a class="reference internal" href="integration-with-client.html">Integration with client</a></li>
<li class="toctree-l3"><a class="reference internal" href="based-on-skulpt.html">Skulpt: Python / JavaScript bridge</a></li>
<li class="toctree-l3"><a class="reference internal" href="project.html">Project</a></li>
<li class="toctree-l3"><a class="reference internal" href="actor.html">Actor: Sprite and Stage</a></li>
<li class="toctree-l3"><a class="reference internal" href="actor-registration.html">Actor-class registration</a></li>
<li class="toctree-l3"><a class="reference internal" href="threading-model.html">Threading model</a></li>
<li class="toctree-l3"><a class="reference internal" href="hat-blocks.html">Hat blocks</a></li>
<li class="toctree-l3"><a class="reference internal" href="syscalls.html">Syscalls</a></li>
<li class="toctree-l3"><a class="reference internal" href="skulpt-pytch-environment.html">Skulpt API / Pytch environment</a></li>
<li class="toctree-l3"><a class="reference internal" href="testing.html">Testing</a></li>
<li class="toctree-l3"><a class="reference internal" href="ide-web-app.html">Web-app</a></li>
<li class="toctree-l3"><a class="reference internal" href="rendering.html">Rendering</a></li>
<li class="toctree-l3"><a class="reference internal" href="hit-detection.html">Collision and click detection</a></li>
<li class="toctree-l3"><a class="reference internal" href="clones.html">Clones</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Sounds</a></li>
<li class="toctree-l3"><a class="reference internal" href="tutorials.html">Tutorials</a></li>
<li class="toctree-l3"><a class="reference internal" href="docstrings.html">Docstrings</a></li>
<li class="toctree-l3"><a class="reference internal" href="attribute-watchers.html">Watching object attributes</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../../webapp/developer/index.html">Webapp</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../medialib/developer/index.html">Media library</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../developer/index.html">Website</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../build-tools/index.html">Tools</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../source-build.html">Source and build information</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../releases/changelog.html">Changelog</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../legal/index.html">Legal information</a></li>
</ul>
<div class="docs-home-link"><hr>
  <ul>
    <li>
      <a href="../../index.html">Pytch help home</a>
    <li>
  </ul>
</div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
  </body>
</html>